/*
    Revolution Engine
    Copyright (C) 2009 Felipe Apablaza

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/


/**
 *
 *  File: Barrier.hpp
 *  Desc: Barrier Sync-Primitive Class. 
 *
 */


#ifndef __REVENG_BARRIER_HPP__
#define __REVENG_BARRIER_HPP__

#include <RevEng/ObjRef.hpp>
#include <RevEng/IMutex.hpp>
#include <RevEng/ICondVar.hpp>

namespace RevEng
{
	class Barrier
	{
	private:
		Int32 m_nCapacity;
		Int32 m_nThreadCount;
		ObjRef<IMutex> m_pMutThreadCount;
		ObjRef<ICondVar> m_pCondThreadCount;

	public:
		Barrier() : m_nCapacity(0), m_nThreadCount(0) 
		{
			m_pCondThreadCount = static_cast<ICondVar*>(IObject::New( REVENG_CONDVAR ));
			m_pMutThreadCount = static_cast<IMutex*>(IObject::New( REVENG_MUTEX ));
		}


		void SetCapacity(Int32 Value)
		{
			m_nCapacity = Value;
		}


		Int32 GetCapacity() const
		{
			return m_nCapacity;
		}


		void Wait() 
		{
			m_pMutThreadCount->Lock();
			++m_nThreadCount;

			if (m_nThreadCount == m_nCapacity)
			{
				m_pCondThreadCount->Broadcast();
				m_nThreadCount = 0;
			}
			else
				m_pCondThreadCount->Wait(m_pMutThreadCount);
			

			m_pMutThreadCount->Unlock();
		}
	};
}

#endif	//__REVENG_BARRIER_HPP__
